home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1991, 2000 Aladdin Enterprises. All rights reserved.
-
- This file is part of AFPL Ghostscript.
-
- AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
- distributor accepts any responsibility for the consequences of using it, or
- for whether it serves any particular purpose or works at all, unless he or
- she says so in writing. Refer to the Aladdin Free Public License (the
- "License") for full details.
-
- Every copy of AFPL Ghostscript must include a copy of the License, normally
- in a plain ASCII text file named PUBLIC. The License grants you the right
- to copy, modify and redistribute AFPL Ghostscript, but only under certain
- conditions described in the License. Among other things, the License
- requires that the copyright notice and this notice be preserved on all
- copies.
- */
-
- /*$Id: gxclist.c,v 1.3 2000/09/19 19:00:34 lpd Exp $ */
- /* Command list document- and page-level code. */
- #include "memory_.h"
- #include "string_.h"
- #include "gx.h"
- #include "gp.h"
- #include "gpcheck.h"
- #include "gserrors.h"
- #include "gxdevice.h"
- #include "gxdevmem.h" /* must precede gxcldev.h */
- #include "gxcldev.h"
- #include "gxclpath.h"
- #include "gsparams.h"
-
- /* GC information */
- #define CLIST_IS_WRITER(cdev) ((cdev)->common.ymin < 0)
- extern_st(st_imager_state);
- private
- ENUM_PTRS_WITH(device_clist_enum_ptrs, gx_device_clist *cdev)
- if (index < st_device_forward_max_ptrs) {
- gs_ptr_type_t ret = ENUM_USING_PREFIX(st_device_forward, 0);
-
- return (ret ? ret : ENUM_OBJ(0));
- }
- if (!CLIST_IS_WRITER(cdev))
- return 0;
- index -= st_device_forward_max_ptrs;
- switch (index) {
- case 0: return ENUM_OBJ((cdev->writer.image_enum_id != gs_no_id ?
- cdev->writer.clip_path : 0));
- case 1: return ENUM_OBJ((cdev->writer.image_enum_id != gs_no_id ?
- cdev->writer.color_space.space : 0));
- default:
- return ENUM_USING(st_imager_state, &cdev->writer.imager_state,
- sizeof(gs_imager_state), index - 2);
- }
- ENUM_PTRS_END
- private
- RELOC_PTRS_WITH(device_clist_reloc_ptrs, gx_device_clist *cdev)
- {
- RELOC_PREFIX(st_device_forward);
- if (!CLIST_IS_WRITER(cdev))
- return;
- if (cdev->writer.image_enum_id != gs_no_id) {
- RELOC_VAR(cdev->writer.clip_path);
- RELOC_VAR(cdev->writer.color_space.space);
- }
- RELOC_USING(st_imager_state, &cdev->writer.imager_state,
- sizeof(gs_imager_state));
- } RELOC_PTRS_END
- public_st_device_clist();
-
- /* Forward declarations of driver procedures */
- private dev_proc_open_device(clist_open);
- private dev_proc_output_page(clist_output_page);
- private dev_proc_close_device(clist_close);
- private dev_proc_get_band(clist_get_band);
- /* Driver procedures defined in other files are declared in gxcldev.h. */
-
- /* Other forward declarations */
- private int clist_put_current_params(P1(gx_device_clist_writer *cldev));
-
- /* The device procedures */
- const gx_device_procs gs_clist_device_procs = {
- clist_open,
- gx_forward_get_initial_matrix,
- gx_default_sync_output,
- clist_output_page,
- clist_close,
- gx_forward_map_rgb_color,
- gx_forward_map_color_rgb,
- clist_fill_rectangle,
- gx_default_tile_rectangle,
- clist_copy_mono,
- clist_copy_color,
- gx_default_draw_line,
- gx_default_get_bits,
- gx_forward_get_params,
- gx_forward_put_params,
- gx_forward_map_cmyk_color,
- gx_forward_get_xfont_procs,
- gx_forward_get_xfont_device,
- gx_forward_map_rgb_alpha_color,
- gx_forward_get_page_device,
- gx_forward_get_alpha_bits,
- clist_copy_alpha,
- clist_get_band,
- gx_default_copy_rop,
- clist_fill_path,
- clist_stroke_path,
- clist_fill_mask,
- gx_default_fill_trapezoid,
- clist_fill_parallelogram,
- clist_fill_triangle,
- gx_default_draw_thin_line,
- gx_default_begin_image,
- gx_default_image_data,
- gx_default_end_image,
- clist_strip_tile_rectangle,
- clist_strip_copy_rop,
- gx_forward_get_clipping_box,
- clist_begin_typed_image,
- clist_get_bits_rectangle,
- gx_forward_map_color_rgb_alpha,
- clist_create_compositor,
- gx_forward_get_hardware_params,
- gx_default_text_begin,
- gx_default_finish_copydevice
- };
-
- /* ------ Define the command set and syntax ------ */
-
- /* Initialization for imager state. */
- /* The initial scale is arbitrary. */
- const gs_imager_state clist_imager_state_initial =
- {gs_imager_state_initial(300.0 / 72.0)};
-
- /*
- * The buffer area (data, data_size) holds a bitmap cache when both writing
- * and reading. The rest of the space is used for the command buffer and
- * band state bookkeeping when writing, and for the rendering buffer (image
- * device) when reading. For the moment, we divide the space up
- * arbitrarily, except that we allocate less space for the bitmap cache if
- * the device doesn't need halftoning.
- *
- * All the routines for allocating tables in the buffer are idempotent, so
- * they can be used to check whether a given-size buffer is large enough.
- */
-
- /*
- * Calculate the desired size for the tile cache.
- */
- private uint
- clist_tile_cache_size(const gx_device * target, uint data_size)
- {
- uint bits_size =
- (data_size / 5) & -align_cached_bits_mod; /* arbitrary */
-
- if (!gx_device_must_halftone(target)) { /* No halftones -- cache holds only Patterns & characters. */
- bits_size -= bits_size >> 2;
- }
- #define min_bits_size 1024
- if (bits_size < min_bits_size)
- bits_size = min_bits_size;
- #undef min_bits_size
- return bits_size;
- }
-
- /*
- * Initialize the allocation for the tile cache. Sets: tile_hash_mask,
- * tile_max_count, tile_table, chunk (structure), bits (structure).
- */
- private int
- clist_init_tile_cache(gx_device * dev, byte * init_data, ulong data_size)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
- byte *data = init_data;
- uint bits_size = data_size;
- /*
- * Partition the bits area between the hash table and the actual
- * bitmaps. The per-bitmap overhead is about 24 bytes; if the
- * average character size is 10 points, its bitmap takes about 24 +
- * 0.5 * 10/72 * xdpi * 10/72 * ydpi / 8 bytes (the 0.5 being a
- * fudge factor to account for characters being narrower than they
- * are tall), which gives us a guideline for the size of the hash
- * table.
- */
- uint avg_char_size =
- (uint)(dev->HWResolution[0] * dev->HWResolution[1] *
- (0.5 * 10 / 72 * 10 / 72 / 8)) + 24;
- uint hc = bits_size / avg_char_size;
- uint hsize;
-
- while ((hc + 1) & hc)
- hc |= hc >> 1; /* make mask (power of 2 - 1) */
- if (hc < 0xff)
- hc = 0xff; /* make allowance for halftone tiles */
- else if (hc > 0xfff)
- hc = 0xfff; /* cmd_op_set_tile_index has 12-bit operand */
- /* Make sure the tables will fit. */
- while (hc >= 3 && (hsize = (hc + 1) * sizeof(tile_hash)) >= bits_size)
- hc >>= 1;
- if (hc < 3)
- return_error(gs_error_rangecheck);
- cdev->tile_hash_mask = hc;
- cdev->tile_max_count = hc - (hc >> 2);
- cdev->tile_table = (tile_hash *) data;
- data += hsize;
- bits_size -= hsize;
- gx_bits_cache_chunk_init(&cdev->chunk, data, bits_size);
- gx_bits_cache_init(&cdev->bits, &cdev->chunk);
- return 0;
- }
-
- /*
- * Initialize the allocation for the bands. Requires: target. Sets:
- * page_band_height (=page_info.band_params.BandHeight), nbands.
- */
- private int
- clist_init_bands(gx_device * dev, gx_device_memory *bdev, uint data_size,
- int band_width, int band_height)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
- int nbands;
-
- if (gdev_mem_data_size(bdev, band_width, band_height) > data_size)
- return_error(gs_error_rangecheck);
- cdev->page_band_height = band_height;
- nbands = (cdev->target->height + band_height - 1) / band_height;
- cdev->nbands = nbands;
- #ifdef DEBUG
- if (gs_debug_c('l') | gs_debug_c(':'))
- dlprintf4("[:]width=%d, band_width=%d, band_height=%d, nbands=%d\n",
- bdev->width, band_width, band_height, nbands);
- #endif
- return 0;
- }
-
- /*
- * Initialize the allocation for the band states, which are used only
- * when writing. Requires: nbands. Sets: states, cbuf, cend.
- */
- private int
- clist_init_states(gx_device * dev, byte * init_data, uint data_size)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
- ulong state_size = cdev->nbands * (ulong) sizeof(gx_clist_state);
-
- /*
- * The +100 in the next line is bogus, but we don't know what the
- * real check should be. We're effectively assuring that at least 100
- * bytes will be available to buffer command operands.
- */
- if (state_size + sizeof(cmd_prefix) + cmd_largest_size + 100 > data_size)
- return_error(gs_error_rangecheck);
- cdev->states = (gx_clist_state *) init_data;
- cdev->cbuf = init_data + state_size;
- cdev->cend = init_data + data_size;
- return 0;
- }
-
- /*
- * Initialize all the data allocations. Requires: target. Sets:
- * page_tile_cache_size, page_info.band_params.BandWidth,
- * page_info.band_params.BandBufferSpace, + see above.
- */
- private int
- clist_init_data(gx_device * dev, byte * init_data, uint data_size)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
- gx_device *target = cdev->target;
- const int band_width =
- cdev->page_info.band_params.BandWidth =
- (cdev->band_params.BandWidth ? cdev->band_params.BandWidth :
- target->width);
- int band_height = cdev->band_params.BandHeight;
- const uint band_space =
- cdev->page_info.band_params.BandBufferSpace =
- (cdev->band_params.BandBufferSpace ?
- cdev->band_params.BandBufferSpace : data_size);
- byte *data = init_data;
- uint size = band_space;
- uint bits_size;
- gx_device_memory bdev;
- gx_device *pbdev = (gx_device *)&bdev;
- int code;
-
- /* Call create_buf_device to get the memory planarity set up. */
- cdev->buf_procs.create_buf_device(&pbdev, target, NULL, NULL, true);
- if (band_height) {
- /*
- * The band height is fixed, so the band buffer requirement
- * is completely determined.
- */
- uint band_data_size =
- gdev_mem_data_size(&bdev, band_width, band_height);
-
- if (band_data_size >= band_space)
- return_error(gs_error_rangecheck);
- bits_size = min(band_space - band_data_size, data_size >> 1);
- } else {
- /*
- * Choose the largest band height that will fit in the
- * rendering-time buffer.
- */
- bits_size = clist_tile_cache_size(target, band_space);
- bits_size = min(bits_size, data_size >> 1);
- band_height = gdev_mem_max_height(&bdev, band_width,
- band_space - bits_size);
- if (band_height == 0)
- return_error(gs_error_rangecheck);
- }
- code = clist_init_tile_cache(dev, data, bits_size);
- if (code < 0)
- return code;
- cdev->page_tile_cache_size = bits_size;
- data += bits_size;
- size -= bits_size;
- code = clist_init_bands(dev, &bdev, size, band_width, band_height);
- if (code < 0)
- return code;
- return clist_init_states(dev, data, data_size - bits_size);
- }
- /*
- * Reset the device state (for writing). This routine requires only
- * data, data_size, and target to be set, and is idempotent.
- */
- private int
- clist_reset(gx_device * dev)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
- int code = clist_init_data(dev, cdev->data, cdev->data_size);
- int nbands;
-
- if (code < 0)
- return (cdev->permanent_error = code);
- /* Now initialize the rest of the state. */
- cdev->permanent_error = 0;
- nbands = cdev->nbands;
- cdev->ymin = cdev->ymax = -1; /* render_init not done yet */
- memset(cdev->tile_table, 0, (cdev->tile_hash_mask + 1) *
- sizeof(*cdev->tile_table));
- cdev->cnext = cdev->cbuf;
- cdev->ccl = 0;
- cdev->band_range_list.head = cdev->band_range_list.tail = 0;
- cdev->band_range_min = 0;
- cdev->band_range_max = nbands - 1;
- {
- int band;
- gx_clist_state *states = cdev->states;
-
- for (band = 0; band < nbands; band++, states++) {
- static const gx_clist_state cls_initial =
- {cls_initial_values};
-
- *states = cls_initial;
- }
- }
- /*
- * Round up the size of the per-tile band mask so that the bits,
- * which follow it, stay aligned.
- */
- cdev->tile_band_mask_size =
- ((nbands + (align_bitmap_mod * 8 - 1)) >> 3) &
- ~(align_bitmap_mod - 1);
- /*
- * Initialize the all-band parameters to impossible values,
- * to force them to be written the first time they are used.
- */
- memset(&cdev->tile_params, 0, sizeof(cdev->tile_params));
- cdev->tile_depth = 0;
- cdev->tile_known_min = nbands;
- cdev->tile_known_max = -1;
- cdev->imager_state = clist_imager_state_initial;
- cdev->clip_path = NULL;
- cdev->clip_path_id = gs_no_id;
- cdev->color_space.byte1 = 0;
- cdev->color_space.id = gs_no_id;
- cdev->color_space.space = 0;
- {
- int i;
-
- for (i = 0; i < countof(cdev->transfer_ids); ++i)
- cdev->transfer_ids[i] = gs_no_id;
- }
- cdev->black_generation_id = gs_no_id;
- cdev->undercolor_removal_id = gs_no_id;
- cdev->device_halftone_id = gs_no_id;
- cdev->image_enum_id = gs_no_id;
- return 0;
- }
- /*
- * Initialize the device state (for writing). This routine requires only
- * data, data_size, and target to be set, and is idempotent.
- */
- private int
- clist_init(gx_device * dev)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
- int code = clist_reset(dev);
-
- if (code >= 0) {
- cdev->image_enum_id = gs_no_id;
- cdev->error_is_retryable = 0;
- cdev->driver_call_nesting = 0;
- cdev->ignore_lo_mem_warnings = 0;
- }
- return code;
- }
-
- /* (Re)init open band files for output (set block size, etc). */
- private int /* ret 0 ok, -ve error code */
- clist_reinit_output_file(gx_device *dev)
- { gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
- int code = 0;
-
- /* bfile needs to guarantee cmd_blocks for: 1 band range, nbands */
- /* & terminating entry */
- int b_block = sizeof(cmd_block) * (cdev->nbands + 2);
-
- /* cfile needs to guarantee one writer buffer */
- /* + one end_clip cmd (if during image's clip path setup) */
- /* + an end_image cmd for each band (if during image) */
- /* + end_cmds for each band and one band range */
- int c_block =
- cdev->cend - cdev->cbuf + 2 + cdev->nbands * 2 + (cdev->nbands + 1);
-
- /* All this is for partial page rendering's benefit, do only */
- /* if partial page rendering is available */
- if ( clist_test_VMerror_recoverable(cdev) )
- { if (cdev->page_bfile != 0)
- code = clist_set_memory_warning(cdev->page_bfile, b_block);
- if (code >= 0 && cdev->page_cfile != 0)
- code = clist_set_memory_warning(cdev->page_cfile, c_block);
- }
- return code;
- }
-
- /* Write out the current parameters that must be at the head of each page */
- /* if async rendering is in effect */
- private int
- clist_emit_page_header(gx_device *dev)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
- int code = 0;
-
- if ((cdev->disable_mask & clist_disable_pass_thru_params)) {
- do
- if ((code = clist_put_current_params(cdev)) >= 0)
- break;
- while ((code = clist_VMerror_recover(cdev, code)) >= 0);
- cdev->permanent_error = (code < 0 ? code : 0);
- if (cdev->permanent_error < 0)
- cdev->error_is_retryable = 0;
- }
- return code;
- }
-
- /* Reset parameters for the beginning of a page. */
- private void
- clist_reset_page(gx_device_clist_writer *cwdev)
- {
- cwdev->page_bfile_end_pos = 0;
- /* Indicate that the colors_used information hasn't been computed. */
- cwdev->page_info.scan_lines_per_colors_used = 0;
- memset(cwdev->page_info.band_colors_used, 0,
- sizeof(cwdev->page_info.band_colors_used));
- }
-
- /* Open the device's bandfiles */
- private int
- clist_open_output_file(gx_device *dev)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
- char fmode[4];
- int code;
-
- if (cdev->do_not_open_or_close_bandfiles)
- return 0; /* external bandfile open/close managed externally */
- cdev->page_cfile = 0; /* in case of failure */
- cdev->page_bfile = 0; /* ditto */
- code = clist_init(dev);
- if (code < 0)
- return code;
- strcpy(fmode, "w+");
- strcat(fmode, gp_fmode_binary_suffix);
- cdev->page_cfname[0] = 0; /* create a new file */
- cdev->page_bfname[0] = 0; /* ditto */
- clist_reset_page(cdev);
- if ((code = clist_fopen(cdev->page_cfname, fmode, &cdev->page_cfile,
- cdev->bandlist_memory, cdev->bandlist_memory,
- true)) < 0 ||
- (code = clist_fopen(cdev->page_bfname, fmode, &cdev->page_bfile,
- cdev->bandlist_memory, cdev->bandlist_memory,
- true)) < 0 ||
- (code = clist_reinit_output_file(dev)) < 0
- ) {
- clist_close_output_file(dev);
- cdev->permanent_error = code;
- cdev->error_is_retryable = 0;
- }
- return code;
- }
-
- /* Close, and free the contents of, the temporary files of a page. */
- /* Note that this does not deallocate the buffer. */
- int
- clist_close_page_info(gx_band_page_info_t *ppi)
- {
- if (ppi->cfile != NULL) {
- clist_fclose(ppi->cfile, ppi->cfname, true);
- ppi->cfile = NULL;
- }
- if (ppi->bfile != NULL) {
- clist_fclose(ppi->bfile, ppi->bfname, true);
- ppi->bfile = NULL;
- }
- return 0;
- }
-
- /* Close the device by freeing the temporary files. */
- /* Note that this does not deallocate the buffer. */
- int
- clist_close_output_file(gx_device *dev)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
-
- return clist_close_page_info(&cdev->page_info);
- }
-
- /* Open the device by initializing the device state and opening the */
- /* scratch files. */
- private int
- clist_open(gx_device *dev)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
- int code;
-
- cdev->permanent_error = 0;
- code = clist_init(dev);
- if (code < 0)
- return code;
- code = clist_open_output_file(dev);
- if ( code >= 0)
- code = clist_emit_page_header(dev);
- return code;
- }
-
- private int
- clist_close(gx_device *dev)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
-
- if (cdev->do_not_open_or_close_bandfiles)
- return 0;
- return clist_close_output_file(dev);
- }
-
- /* The output_page procedure should never be called! */
- private int
- clist_output_page(gx_device * dev, int num_copies, int flush)
- {
- return_error(gs_error_Fatal);
- }
-
- /* Reset (or prepare to append to) the command list after printing a page. */
- int
- clist_finish_page(gx_device *dev, bool flush)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
- int code;
-
- if (flush) {
- if (cdev->page_cfile != 0)
- clist_rewind(cdev->page_cfile, true, cdev->page_cfname);
- if (cdev->page_bfile != 0)
- clist_rewind(cdev->page_bfile, true, cdev->page_bfname);
- clist_reset_page(cdev);
- } else {
- if (cdev->page_cfile != 0)
- clist_fseek(cdev->page_cfile, 0L, SEEK_END, cdev->page_cfname);
- if (cdev->page_bfile != 0)
- clist_fseek(cdev->page_bfile, 0L, SEEK_END, cdev->page_bfname);
- }
- code = clist_init(dev); /* reinitialize */
- if (code >= 0)
- code = clist_reinit_output_file(dev);
- if (code >= 0)
- code = clist_emit_page_header(dev);
-
- return code;
- }
-
- /* ------ Writing ------ */
-
- /* End a page by flushing the buffer and terminating the command list. */
- int /* ret 0 all-ok, -ve error code, or +1 ok w/low-mem warning */
- clist_end_page(gx_device_clist_writer * cldev)
- {
- int code = cmd_write_buffer(cldev, cmd_opv_end_page);
- cmd_block cb;
- int ecode = 0;
-
- if (code >= 0) {
- /*
- * Write the terminating entry in the block file.
- * Note that because of copypage, there may be many such entries.
- */
- cb.band_min = cb.band_max = cmd_band_end;
- cb.pos = (cldev->page_cfile == 0 ? 0 : clist_ftell(cldev->page_cfile));
- code = clist_fwrite_chars(&cb, sizeof(cb), cldev->page_bfile);
- if (code > 0)
- code = 0;
- }
- if (code >= 0) {
- clist_compute_colors_used(cldev);
- ecode |= code;
- cldev->page_bfile_end_pos = clist_ftell(cldev->page_bfile);
- }
- if (code < 0)
- ecode = code;
-
- /* Reset warning margin to 0 to release reserve memory if mem files */
- if (cldev->page_bfile != 0)
- clist_set_memory_warning(cldev->page_bfile, 0);
- if (cldev->page_cfile != 0)
- clist_set_memory_warning(cldev->page_cfile, 0);
-
- #ifdef DEBUG
- if (gs_debug_c('l') | gs_debug_c(':'))
- dlprintf2("[:]clist_end_page at cfile=%ld, bfile=%ld\n",
- cb.pos, cldev->page_bfile_end_pos);
- #endif
- return 0;
- }
-
- /* Compute the set of used colors in the page_info structure. */
- void
- clist_compute_colors_used(gx_device_clist_writer *cldev)
- {
- int nbands = cldev->nbands;
- int bands_per_colors_used =
- (nbands + PAGE_INFO_NUM_COLORS_USED - 1) /
- PAGE_INFO_NUM_COLORS_USED;
- int band;
-
- cldev->page_info.scan_lines_per_colors_used =
- cldev->page_band_height * bands_per_colors_used;
- memset(cldev->page_info.band_colors_used, 0,
- sizeof(cldev->page_info.band_colors_used));
- for (band = 0; band < nbands; ++band) {
- int entry = band / bands_per_colors_used;
-
- cldev->page_info.band_colors_used[entry].or |=
- cldev->states[band].colors_used.or;
- cldev->page_info.band_colors_used[entry].slow_rop |=
- cldev->states[band].colors_used.slow_rop;
- }
- }
-
- /* Recover recoverable VM error if possible without flushing */
- int /* ret -ve err, >= 0 if recovered w/# = cnt pages left in page queue */
- clist_VMerror_recover(gx_device_clist_writer *cldev,
- int old_error_code)
- {
- int code = old_error_code;
- int pages_remain;
-
- if (!clist_test_VMerror_recoverable(cldev) ||
- !cldev->error_is_retryable ||
- old_error_code != gs_error_VMerror
- )
- return old_error_code;
-
- /* Do some rendering, return if enough memory is now free */
- do {
- pages_remain =
- (*cldev->free_up_bandlist_memory)( (gx_device *)cldev, false );
- if (pages_remain < 0) {
- code = pages_remain; /* abort, error or interrupt req */
- break;
- }
- if (clist_reinit_output_file( (gx_device *)cldev ) == 0) {
- code = pages_remain; /* got enough memory to continue */
- break;
- }
- } while (pages_remain);
-
- if_debug1('L', "[L]soft flush of command list, status: %d\n", code);
- return code;
- }
-
- /* If recoverable VM error, flush & try to recover it */
- int /* ret 0 ok, else -ve error */
- clist_VMerror_recover_flush(gx_device_clist_writer *cldev,
- int old_error_code)
- {
- int free_code = 0;
- int reset_code = 0;
- int code;
-
- /* If the device has the ability to render partial pages, flush
- * out the bandlist, and reset the writing state. Then, get the
- * device to render this band. When done, see if there's now enough
- * memory to satisfy the minimum low-memory guarantees. If not,
- * get the device to render some more. If there's nothing left to
- * render & still insufficient memory, declare an error condition.
- */
- if (!clist_test_VMerror_recoverable(cldev) ||
- old_error_code != gs_error_VMerror
- )
- return old_error_code; /* sorry, don't have any means to recover this error */
- free_code = (*cldev->free_up_bandlist_memory)( (gx_device *)cldev, true );
-
- /* Reset the state of bands to "don't know anything" */
- reset_code = clist_reset( (gx_device *)cldev );
- if (reset_code >= 0)
- reset_code = clist_open_output_file( (gx_device *)cldev );
- if ( reset_code >= 0 &&
- (cldev->disable_mask & clist_disable_pass_thru_params)
- )
- reset_code = clist_put_current_params(cldev);
- if (reset_code < 0) {
- cldev->permanent_error = reset_code;
- cldev->error_is_retryable = 0;
- }
-
- code = (reset_code < 0 ? reset_code : free_code < 0 ? old_error_code : 0);
- if_debug1('L', "[L]hard flush of command list, status: %d\n", code);
- return code;
- }
-
- /* Write the target device's current parameter list */
- private int /* ret 0 all ok, -ve error */
- clist_put_current_params(gx_device_clist_writer *cldev)
- {
- gx_device *target = cldev->target;
- gs_c_param_list param_list;
- int code;
-
- /*
- * If a put_params call fails, the device will be left in a closed
- * state, but higher-level code won't notice this fact. We flag this by
- * setting permanent_error, which prevents writing to the command list.
- */
-
- if (cldev->permanent_error)
- return cldev->permanent_error;
- gs_c_param_list_write(¶m_list, cldev->memory);
- code = (*dev_proc(target, get_params))
- (target, (gs_param_list *)¶m_list);
- if (code >= 0) {
- gs_c_param_list_read(¶m_list);
- code = cmd_put_params( cldev, (gs_param_list *)¶m_list );
- }
- gs_c_param_list_release(¶m_list);
-
- return code;
- }
-
- /* ---------------- Driver interface ---------------- */
-
- private int
- clist_get_band(gx_device * dev, int y, int *band_start)
- {
- gx_device_clist_writer * const cdev =
- &((gx_device_clist *)dev)->writer;
- int band_height = cdev->page_band_height;
- int start;
-
- if (y < 0)
- y = 0;
- else if (y >= dev->height)
- y = dev->height;
- *band_start = start = y - y % band_height;
- return min(dev->height - start, band_height);
- }
-